#pragma once
#include"Socket.hpp"
#include "InetAddr.hpp"
#include <functional>
//设置函数对象

using namespace socket_ns;
static const int gport = 8888;

using service_io_t = std::function<void(SockSPtr, InetAddr &)>;

class TcpServer
{

public:
  TcpServer(service_io_t service,  uint16_t port = gport) 
  : _port(port)
  , _listensock(std::make_shared<TcpSocket>())
  , _isrunning(false)
  , _service(service) 
  {
    _listensock->BuildListenSocket(_port);
  }

  class ThreadData
  {
  public:
    SockSPtr _sockfd;
    TcpServer *_self;
    InetAddr _addr;//给InetAddr再添加一个无参构造
  public:
    ThreadData(SockSPtr sockfd, TcpServer *self, const InetAddr &addr) : _sockfd(sockfd), _self(self), _addr(addr) 
    {
    }
  };

  void Loop()
  {
    // signal(SIGCHLD, SIG_IGN);
    _isrunning = true;
    while (_isrunning)
    {
      InetAddr client;
      SockSPtr newsock = _listensock->Accepter(&client);
      if(newsock == nullptr)
      {
        continue;
      }

      LOG(INFO, "get a new link, client info : %s, sockfd is: %d\n", client.AddrStr().c_str(), newsock->Sockfd());
      
      // version2-----多线程版本 --- 不能关闭fd,也不需要
      pthread_t tid;
      ThreadData* td = new ThreadData(newsock, this, client);
      pthread_create(&tid, nullptr, Execute, td);
    }
    _isrunning = false;
  }

  static void *Execute(void *args)
  {
    pthread_detach(pthread_self());

    ThreadData* td = static_cast<ThreadData *>(args);
    //直接回调我们定义的函数对象
    td->_self->_service(td->_sockfd, td->_addr);
    //处理完了，直接关闭
    td->_sockfd->Close();

    delete td;
    return nullptr;
  }

  ~TcpServer()
  {
  }

private:
  uint16_t _port;
//   int _listensockfd;
//   定义套接字对象
  SockSPtr _listensock;
  bool _isrunning;
  service_io_t _service;
};
